package com.itany.book.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itany.ApplicationContextHold;
import com.itany.book.service.IBookService;
import com.itany.constant.Constant;
import com.itany.dao.BookMapper;
import com.itany.dao.BookTypeMapper;
import com.itany.exception.RequestParamsException;
import com.itany.pojo.Book;
import com.itany.pojo.BookType;
import com.itany.pojo.User;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;


@Service
@com.alibaba.dubbo.config.annotation.Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class BookServiceImpl implements IBookService {

    StringRedisTemplate template = ApplicationContextHold.getBean(StringRedisTemplate.class);


    @Autowired(required = false)
    BookTypeMapper bookTypeMapper;

    @Autowired(required = false)
    BookMapper bookMapper;


    @Autowired
    private HttpSolrClient solrClient;


    @Override
    public void addDoc() {
        try {
            List<Book> books = bookMapper.selectAllBooks();
            for(Book book : books) {
                SolrInputDocument document = new SolrInputDocument();
                document.addField("id",book.getId());
                document.addField("bookname",book.getBookname());
                document.addField("author",book.getAuthor());
                document.addField("publishdate",new SimpleDateFormat("yyyy-MM-dd").format(book.getPublishdate()));
                document.addField("price",String.valueOf(book.getPrice()));
                document.addField("bookintroduce",book.getBookintroduce());
                document.addField("imgurl",book.getImgurl());
                document.addField("pressname",book.getPress().getName());
                solrClient.add(document);
            }
            solrClient.commit();

        }catch (Exception e){
            e.printStackTrace();
            try {
                solrClient.rollback();
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }

    }

    @Override
    public List<Map<String, String>> findDoc(String keyWord) {
        //最后封装返回的数据集合
        List<Map<String, String>> list = new ArrayList<>();
        try {
            //声明查询语句
            String q="*:*";
            if(keyWord!=null && !"".equalsIgnoreCase(keyWord)){
                q="bookname:"+keyWord+" OR author:"+keyWord+" OR pressname:"+keyWord+" OR bookintroduce:"+keyWord;
            }
            //声明查询请求对象
            SolrQuery solrQuery = new SolrQuery();
            //查询语句赋值
            solrQuery.setQuery(q);
            //开启高亮查询
            solrQuery.setHighlight(true);
            //设置高亮的html标签
            solrQuery.setHighlightSimplePre("<font color='red'>");
            solrQuery.setHighlightSimplePost("</font>");
            //分页参数设置
          /*solrQuery.setStart((pageNo-1)*pageSize);
            solrQuery.setRows(pageSize);*/
            //设置参与高亮的列
            solrQuery.setParam("hl.fl","*");
            //执行查询
            QueryResponse response = solrClient.query(solrQuery);
            //获取查询结果集
            SolrDocumentList documentList =response.getResults();
            //获取总数据条数(select count(*))
            Long count= documentList.getNumFound();
            System.out.println("总数据条数:"+count);
            //获取高亮后的数据
            for(int i=0;i<documentList.size();i++){
                //声明一个单个的结果集对象
                Map<String, String> vo = new HashMap<>();
                //先获取结果集数据的ID值
                SolrDocument solrDocument = documentList.get(i);
                String id = ""+solrDocument.get("id");
                //调用response的获取高亮数据方法
                Map<String,List<String>> map = response.getHighlighting().get(id);
                //取出一个field高亮后的值
                List<String> booknames = map.get("bookname");
                System.out.println("=========>书名"+booknames);
                //判断当前field是否有高亮数据
                if(booknames!=null){
                    vo.put("bookname",booknames.get(0));
                }else{
                    vo.put("bookname",solrDocument.get("bookname")+"");
                }

                List<String> authors = map.get("author");
                //判断当前field是否有高亮数据
                if(authors!=null){
                    vo.put("author",authors.get(0));
                }else{
                    vo.put("author",solrDocument.get("author")+"");
                }

                List<String> pressnames = map.get("pressname");
                //判断当前field是否有高亮数据
                if(pressnames!=null){
                    vo.put("pressname",pressnames.get(0));
                }else{
                    vo.put("pressname",solrDocument.get("pressname")+"");
                }
                List<String> bookintroduces = map.get("bookintroduce");
                //判断当前field是否有高亮数据
                if(bookintroduces!=null){
                    vo.put("bookintroduce",bookintroduces.get(0));
                }else{
                    vo.put("bookintroduce",solrDocument.get("bookintroduce")+"");
                }

                vo.put("publishdate",solrDocument.get("publishdate")+"");
                vo.put("price",solrDocument.get("price")+"");
                vo.put("imgurl",solrDocument.get("imgurl")+"");
                vo.put("id",solrDocument.get("id")+"");
                list.add(vo);

            }


        }catch (Exception e){
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 查找所有的图书类别用于侧边栏显示
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public Map<String, Object> findAllTypes() {
        //最外层的map
        Map<String, Object> allTypes = new HashMap<>();
        //先从redis中找，找不到再从数据库查询
        String jsonStr = template.opsForValue().get(Constant.BOOK_TYPE_REDIS_KEY);
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        if(jsonObject == null) {
            List<BookType> bookTypes = bookTypeMapper.selectTypesByParentId(null);

            Map<String, Object> finalAllTypes = allTypes;
            bookTypes.forEach(bookType -> {
                //第二层的list
                List<Map<String,Object>> secondLevelTypes = new ArrayList<>();
                //获取第二层的图书名名称
                List<BookType> secondBookTypes = bookTypeMapper.selectTypesByParentId(bookType.getId());

                for (BookType secondBookType : secondBookTypes) {
                    //第三层的map
                    Map<String,Object> thirdLevelTypes = new HashMap<>();
                    thirdLevelTypes.put("name",secondBookType.getTypetext());
                    //第三层的图书类型
                    List<BookType> thirdBookTypes = bookTypeMapper.selectTypesByParentId(secondBookType.getId());
                    //第三层图书名称的数组
                    List<String> fourthLevelTypes = new ArrayList<>();
                    for (BookType thirdBookType:thirdBookTypes) {
                        fourthLevelTypes.add(thirdBookType.getTypetext());
                    }
                    thirdLevelTypes.put("content",fourthLevelTypes);
                    secondLevelTypes.add(thirdLevelTypes);
                }
                finalAllTypes.put(""+bookType.getId(), secondLevelTypes);
            });
            template.opsForValue().set(Constant.BOOK_TYPE_REDIS_KEY,JSON.toJSONString(allTypes));
        }else{
            allTypes = jsonObject;
        }

        return allTypes;
    }

    /**
     * 根据书籍id查找书籍信息
     *
     * @param id
     * @return
     */
    @Override
    public Map findById(String id) throws RequestParamsException {

        if(id==null || "".equals(id.trim())){
            throw new RequestParamsException("请求参数缺失");
        }
        Integer idInt;
        try {
            idInt = Integer.parseInt(id);
        } catch (NumberFormatException e) {
            throw new RequestParamsException("请求参数格式错误");
        }
        Map<Object, Object> bookmap = template.opsForHash().entries("book"+idInt);
        if(bookmap.isEmpty()) {
            Book book = bookMapper.selectById(idInt);
            bookmap = new HashMap();
            bookmap.put("bookname",book.getBookname());
            bookmap.put("author",book.getAuthor());
            bookmap.put("price",String.valueOf(book.getPrice()));
            bookmap.put("publishdate",new SimpleDateFormat("yyyy-MM-dd").format(book.getPublishdate()));
            bookmap.put("bookintroduce",book.getBookintroduce());
            bookmap.put("pressname",book.getPress().getName());
            String imgurl = book.getImgurl();
            if(!imgurl.contains("http") && !imgurl.contains("https")){
                imgurl = "http://localhost:9001/manager"+imgurl;
            }
            bookmap.put("imgurl",imgurl);
            template.opsForHash().putAll("book"+idInt,bookmap);
        }
        return bookmap;
    }

    /**
     * 添加购物车到redis,没有则添加，有则增加（hset）
     *
     * @param id
     */
    @Override
    public void addShoppingCar(String id, User user) throws RequestParamsException {
        if(id==null || "".equals(id.trim())){
            throw new RequestParamsException("请求参数缺失");
        }
        Integer idInt;
        try {
            idInt = Integer.parseInt(id);
        } catch (NumberFormatException e) {
            throw new RequestParamsException("请求参数格式错误");
        }
        Object o = template.opsForHash().get(Constant.SHOPPING_CART_REDIS_KEY + user.getId(), id);
        if(o==null){
            template.opsForHash().put(Constant.SHOPPING_CART_REDIS_KEY  + user.getId(), id,""+1);
        }else{
            template.opsForHash().increment(Constant.SHOPPING_CART_REDIS_KEY  + user.getId(),id,1);
        }
    }
}
